package com.morder.widget;

import com.morder.R;

import android.content.Context;
import android.util.AttributeSet;
import android.util.Log;
import android.view.LayoutInflater;
import android.view.MotionEvent;
import android.view.View;
import android.view.ViewGroup;
import android.view.animation.LinearInterpolator;
import android.view.animation.RotateAnimation;
import android.widget.AbsListView;
import android.widget.AbsListView.OnScrollListener;
import android.widget.ImageView;
import android.widget.ListAdapter;
import android.widget.ListView;
import android.widget.ProgressBar;
import android.widget.RelativeLayout;
import android.widget.TextView;

/**
 * 重写ListView控件，增加了头部，状态栏等控件。
 * (此控件作者为johannilsson，为国内某位作者二次开发，本人又做了一点点的修改；感谢原作者和二次开发作者的辛勤劳动)
 * 
 * @author johannilsson https://github.com/johannilsson/android-pulltorefresh
 */
public class PullToRefreshListView extends ListView implements OnScrollListener {

  // 状态
  private static final int TAP_TO_REFRESH = 1;
  private static final int PULL_TO_REFRESH = 2;
  private static final int RELEASE_TO_REFRESH = 3;
  private static final int REFRESHING = 4;

  // 数据条数
  private int itemRowCount = 0;
  // 分页条数
  private int pageSize = 0;

  private OnRefreshListener mOnRefreshListener;

  // 监听对ListView的滑动动作
  private OnScrollListener mOnScrollListener;
  private LayoutInflater mInflater;

  // 顶部刷新时出现的控件
  private RelativeLayout mRefreshView;
  private TextView mRefreshViewText;
  private ImageView mRefreshViewImage;
  private ProgressBar mRefreshViewProgress;
  private TextView mRefreshViewLastUpdated;

  private int mCurrentScrollState;// 当前滑动状态
  private int mRefreshState;// 当前刷新状态

  private RotateAnimation mFlipAnimation;
  private RotateAnimation mReverseFlipAnimation;

  private int mRefreshViewHeight;
  private int mRefreshOriginalTopPadding;
  private int mLastMotionY;

  private boolean mBounceHack;

  public PullToRefreshListView(Context context) {
    super(context);
    init(context);
  }

  public PullToRefreshListView(Context context, AttributeSet attrs) {
    super(context, attrs);
    init(context);
  }

  public PullToRefreshListView(Context context, AttributeSet attrs, int defStyle) {
    super(context, attrs, defStyle);
    init(context);
  }

  /**
   * 初始化控件和动画
   * 
   * @param context
   */
  private void init(Context context) {
    mFlipAnimation = new RotateAnimation(0, -180, RotateAnimation.RELATIVE_TO_SELF, 0.5f,
        RotateAnimation.RELATIVE_TO_SELF, 0.5f);
    mFlipAnimation.setInterpolator(new LinearInterpolator());
    mFlipAnimation.setDuration(250);
    mFlipAnimation.setFillAfter(true);
    mReverseFlipAnimation = new RotateAnimation(-180, 0, RotateAnimation.RELATIVE_TO_SELF, 0.5f,
        RotateAnimation.RELATIVE_TO_SELF, 0.5f);
    mReverseFlipAnimation.setInterpolator(new LinearInterpolator());
    mReverseFlipAnimation.setDuration(250);
    mReverseFlipAnimation.setFillAfter(true);

    mInflater = (LayoutInflater) context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);

    mRefreshView = (RelativeLayout) mInflater.inflate(R.layout.pull_to_refresh_header, this, false);
    mRefreshViewText = (TextView) mRefreshView.findViewById(R.id.pull_to_refresh_text);
    mRefreshViewImage = (ImageView) mRefreshView.findViewById(R.id.pull_to_refresh_image);
    mRefreshViewProgress = (ProgressBar) mRefreshView.findViewById(R.id.pull_to_refresh_progress);
    mRefreshViewLastUpdated = (TextView) mRefreshView.findViewById(R.id.pull_to_refresh_updated_at);

    mRefreshViewImage.setMinimumHeight(50);
    mRefreshView.setOnClickListener(new OnClickRefreshListener());
    mRefreshOriginalTopPadding = mRefreshView.getPaddingTop();

    mRefreshState = TAP_TO_REFRESH;

    // 为ListView头部添加view
    addHeaderView(mRefreshView);

    super.setOnScrollListener(this);

    measureView(mRefreshView);

    mRefreshViewHeight = mRefreshView.getMeasuredHeight();
  }

  @Override
  protected void onAttachedToWindow() {
    setSelection(1);
  }

  @Override
  public void setAdapter(ListAdapter adapter) {
    super.setAdapter(adapter);

    setSelection(1);
  }

  @Override
  public void setOnScrollListener(AbsListView.OnScrollListener l) {
    mOnScrollListener = l;
  }

  public void setOnRefreshListener(OnRefreshListener onRefreshListener) {
    mOnRefreshListener = onRefreshListener;
  }

  public void setLastUpdated(CharSequence lastUpdated) {
    if (lastUpdated != null) {
      mRefreshViewLastUpdated.setVisibility(View.VISIBLE);
      mRefreshViewLastUpdated.setText(lastUpdated);
    } else {
      mRefreshViewLastUpdated.setVisibility(View.GONE);
    }
  }

  /**
   * 触摸
   */
  @Override
  public boolean onTouchEvent(MotionEvent event) {
    final int y = (int) event.getY();
    mBounceHack = false;

    switch (event.getAction()) {
    case MotionEvent.ACTION_UP:
      if (!isVerticalScrollBarEnabled()) {
        setVerticalScrollBarEnabled(true);
      }
      if (getFirstVisiblePosition() == 0 && mRefreshState != REFRESHING) {
        if ((mRefreshView.getBottom() >= mRefreshViewHeight || mRefreshView.getTop() >= 0)
            && mRefreshState == RELEASE_TO_REFRESH) {
          mRefreshState = REFRESHING;
          prepareForRefresh();// 准备刷新
          onRefresh();// 刷新
        } else if (mRefreshView.getBottom() < mRefreshViewHeight || mRefreshView.getTop() <= 0) {
          resetHeader();// 中止刷新
          setSelection(1);
        }
      }
      break;
    case MotionEvent.ACTION_DOWN:
      mLastMotionY = y;// 获得按下y轴位置
      break;
    case MotionEvent.ACTION_MOVE:
      // 计算边距
      applyHeaderPadding(event);
      break;
    }
    return super.onTouchEvent(event);
  }

  private void applyHeaderPadding(MotionEvent ev) {
    int pointerCount = ev.getHistorySize();

    for (int p = 0; p < pointerCount; p++) {
      if (mRefreshState == RELEASE_TO_REFRESH) {
        if (isVerticalFadingEdgeEnabled()) {
          setVerticalScrollBarEnabled(false);
        }

        int historicalY = (int) ev.getHistoricalY(p);

        int topPadding = (int) (((historicalY - mLastMotionY) - mRefreshViewHeight) / 1.7);

        mRefreshView.setPadding(mRefreshView.getPaddingLeft(), topPadding, mRefreshView.getPaddingRight(),
            mRefreshView.getPaddingBottom());
      }
    }
  }

  private void resetHeaderPadding() {
    mRefreshView.setPadding(mRefreshView.getPaddingLeft(), mRefreshOriginalTopPadding, mRefreshView.getPaddingRight(),
        mRefreshView.getPaddingBottom());
  }

  private void resetHeader() {
    if (mRefreshState != TAP_TO_REFRESH) {
      mRefreshState = TAP_TO_REFRESH;
      resetHeaderPadding();
      mRefreshViewText.setText(R.string.pull_to_refresh_tap_label);
      mRefreshViewImage.setImageResource(R.drawable.ic_pulltorefresh_arrow);// 换成箭头
      mRefreshViewImage.clearAnimation();// 清除动画
      mRefreshViewImage.setVisibility(View.GONE);// 隐藏图标
      mRefreshViewProgress.setVisibility(View.GONE);// 隐藏进度条
    }
  }

  private void measureView(View child) {
    ViewGroup.LayoutParams p = child.getLayoutParams();
    if (p == null) {
      p = new ViewGroup.LayoutParams(ViewGroup.LayoutParams.FILL_PARENT, ViewGroup.LayoutParams.WRAP_CONTENT);
    }

    int childWidthSpec = ViewGroup.getChildMeasureSpec(0, 0 + 0, p.width);
    int lpHeight = p.height;
    int childHeightSpec;
    if (lpHeight > 0) {
      childHeightSpec = MeasureSpec.makeMeasureSpec(lpHeight, MeasureSpec.EXACTLY);
    } else {
      childHeightSpec = MeasureSpec.makeMeasureSpec(0, MeasureSpec.UNSPECIFIED);
    }
    child.measure(childWidthSpec, childHeightSpec);
  }

  @Override
  public void onScroll(AbsListView view, int firstVisibleItem, int visibleItemCount, int totalItemCount) {
    if (mCurrentScrollState == SCROLL_STATE_TOUCH_SCROLL && mRefreshState != REFRESHING) {
      if (firstVisibleItem == 0) {
        mRefreshViewImage.setVisibility(View.VISIBLE);
        if ((mRefreshView.getBottom() >= mRefreshViewHeight + 20 || mRefreshView.getTop() >= 0)
            && mRefreshState != RELEASE_TO_REFRESH) {
          mRefreshViewText.setText(R.string.pull_to_refresh_release_label);
          mRefreshViewImage.clearAnimation();
          mRefreshViewImage.startAnimation(mFlipAnimation);
          mRefreshState = RELEASE_TO_REFRESH;
        } else if (mRefreshView.getBottom() < mRefreshViewHeight + 20 && mRefreshState != PULL_TO_REFRESH) {
          mRefreshViewText.setText(R.string.pull_to_refresh_pull_label);
          if (mRefreshState != TAP_TO_REFRESH) {
            mRefreshViewImage.clearAnimation();
            mRefreshViewImage.startAnimation(mReverseFlipAnimation);
          }
          mRefreshState = PULL_TO_REFRESH;
        }
      } else {
        mRefreshViewImage.setVisibility(View.GONE);
        resetHeader();
      }
    } else if (mCurrentScrollState == SCROLL_STATE_FLING && firstVisibleItem == 0 && mRefreshState != REFRESHING) {
      setSelection(1);
      mBounceHack = true;
    } else if (mBounceHack && mCurrentScrollState == SCROLL_STATE_FLING) {
      setSelection(1);
    }

    if (mOnScrollListener != null) {
      mOnScrollListener.onScroll(view, firstVisibleItem, visibleItemCount, totalItemCount);
    }
  }

  @Override
  public void onScrollStateChanged(AbsListView view, int scrollState) {
    mCurrentScrollState = scrollState;

    if (mCurrentScrollState == SCROLL_STATE_IDLE) {
      mBounceHack = false;
    }

    if (mOnScrollListener != null) {
      mOnScrollListener.onScrollStateChanged(view, scrollState);
    }
  }

  public void prepareForRefresh() {
    resetHeaderPadding();
    mRefreshViewImage.setVisibility(View.GONE);
    mRefreshViewImage.setImageDrawable(null);
    mRefreshViewProgress.setVisibility(View.VISIBLE);
    mRefreshViewText.setText(R.string.pull_to_refresh_refreshing_label);
    mRefreshState = REFRESHING;
  }

  public void onRefresh() {
    if (mOnRefreshListener != null) {
      mOnRefreshListener.onRefresh();
    }
  }

  public void onRefreshComplete(CharSequence lastUpdated) {
    setLastUpdated(lastUpdated);
    onRefreshComplete();
  }

  public void onRefreshComplete() {
    resetHeader();
    int bottomPosition = mRefreshView.getBottom();
    Log.i("bottom", "pull:rows:" + String.valueOf(itemRowCount) + ",pageSize:" + String.valueOf(pageSize));
    if (bottomPosition > 0) {
      invalidateViews();
      setSelection(1);// 选择第二项
    }
    // 若数据行数小于本次分页行数，则隐藏顶部和底部控件
    if (pageSize > 0 && itemRowCount < pageSize) {
      removeHeaderView(mRefreshView);
    }
  }

  private class OnClickRefreshListener implements OnClickListener {

    @Override
    public void onClick(View v) {
      if (mRefreshState != REFRESHING) {
        prepareForRefresh();
        onRefresh();
      }
    }
  }

  public void SetDataRow(int row) {
    itemRowCount = row;
  }

  public void SetPageSize(int size) {
    pageSize = size;
  }

  public interface OnRefreshListener {
    public void onRefresh();
  }
}
